# -*- coding:utf-8 -*-
import time
import os
import hashlib
import uuid
import aiofiles
from fastapi import Request, UploadFile, HTTPException
from sqlalchemy.exc import OperationalError
from app.entity.system import SysAttach
from core.curd import CRUDBase, IBaseDao
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncEngine
from config.app import get_config


class SysAttachDao(IBaseDao):
    """
    测试模块服务层
    """

    def __init__(self, req: Request):
        self.db_session: AsyncEngine = req.app.state.db_async_session
        self.base = CRUDBase(SysAttach)

    async def upload(self, file: UploadFile):
        settings = get_config()

        now = time.localtime()
        ymd = "%04d%02d%02d" % (now.tm_year, now.tm_mon, now.tm_mday)
        folder = settings.UPLOAD_PATH + "/" + ymd + "/"

        if os.path.exists(folder) == False:
            os.mkdir(folder)

        md5 = hashlib.md5(str(uuid.uuid4()).encode()).hexdigest()

        fileName = md5 + '.' + file.filename.split(".")[-1]
        filePath = "/" + ymd + "/" + fileName
        fileUrl = "/sys/attach/download/" + md5

        with open(folder + fileName, 'wb') as f:
            # 流式写出大型文件，这里的10代表10MB
            for chunk in iter(lambda: file.file.read(1024 * 1024 * 10), b''):
                f.write(chunk)

        return {"name": file.filename, "size": file.size, "url": fileUrl, "path": filePath, "md5": md5, "platform": "local"}

    async def download(self, path: str):
        settings = get_config()

        async with self.db_session() as db:
            try:
                ret = await db.execute(select(SysAttach).where(SysAttach.md5 == path))
                return ret.scalars().first()

                # if file is None:
                #     return None
                # else:
                #     async with aiofiles.open(settings.UPLOAD_PATH + file.path, mode='rb') as f:
                #         content = await f.read()
                #         return content

            except OperationalError as e:
                raise HTTPException(status_code=500, detail=str(e))
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e))
            finally:
                await db.close()

    @classmethod
    async def instance(cls, req: Request):
        return cls(req)
